package net.sf.rose.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;

/**
 * 类说明：字符串通用处理类
 * 
 * @author fengjian
 * @since 2014-6-17
 */
public class StringUtil {

	/**
	 * 判断字符串是否为Null或空
	 * 
	 * @param str 待判断的字符器
	 * @return 结果
	 */
	public static boolean isEmpty(Object obj) {
		if (obj == null) {
			return true;
		}
		return obj.toString().trim().length() == 0;
	}

	/**
	 * 将对象类型数据转换成字符串
	 * 
	 * @param obj - 对象类型数据
	 * @return
	 */
	public static String convertString(Object obj) {
		if (obj == null) {
			return null;
		} else {
			String s = obj.toString().trim();
			if (s.equals("")) {
				return null;
			} else if (s.equals("null")) {
				return null;
			}
			return s;
		}
	}

	/**
	 * 将对象类型数据转换成数字整型
	 * 
	 * @param obj - 对象类型数据
	 * @return
	 */
	public static int convertInt(Object obj, int defaultValue) {
		if (obj == null) {
			return defaultValue;
		} else {
			String s = obj.toString().trim();
			if (s.equals("")) {
				return defaultValue;
			} else if (s.equals("null")) {
				return defaultValue;
			}
			return Integer.parseInt(s);
		}
	}

	/**
	 * 将对象类型数据转换成日期类型
	 * 
	 * @param obj - 对象类型数据
	 * @return
	 */
	public static Date convertDate(Object obj) {
		if (obj == null) {
			return null;
		} else {
			String s = obj.toString().trim();
			if (s.equals("")) {
				return null;
			} else if (s.equals("null")) {
				return null;
			}
			return new DateFormat().format(s);
		}
	}

	/**
	 * 判断二个参数是否相等
	 * 
	 * @param o1 参数1
	 * @param o2 参数2
	 * @return 是否相等
	 */
	public static boolean equals(Object o1, Object o2) {
		boolean flag = false;
		if (o1 != null) {
			if (o2 == null) {
				flag = false;
			} else if (o2.equals(o1)) {
				flag = true;
			}
		} else {
			if (o2 == null) {
				flag = true;
			}
		}
		return flag;
	}

	/**
	 * 判断二个参数是否相等
	 * 
	 * @param o1 参数1
	 * @param o2 参数2
	 * @return 是否相等
	 */
	public static boolean equalsTime(Date o1, Date o2) {
		boolean flag = false;
		if (o1 != null) {
			if (o2 != null) {
				String d1 = DateFormat.format(o1, DateFormat.DATE_FORMAT_4);
				String d2 = DateFormat.format(o2, DateFormat.DATE_FORMAT_4);
				if (d1.equals(d2)) {
					flag = true;
				}
			}
		} else {
			if (o2 == null) {
				flag = true;
			}
		}
		return flag;
	}

	/**
	 * 返回指定的字符串首字母大写
	 * 
	 * @param string 待格式化的字符串
	 * @return 格式化的字符串
	 */
	public static String firstLetterUpper(String string) {
		return Character.toUpperCase(string.charAt(0)) + string.substring(1);
	}

	/**
	 * 将流文件转换成字符串
	 * 
	 * @param in 待转化的文件流
	 * @return 转换后的字符串
	 */
	public static String toString(InputStream in) {
		byte[] b = new byte[4096];
		StringBuilder result = new StringBuilder();
		try {
			for (int n; (n = in.read(b)) != -1;) {
				result.append(new String(b, 0, n));
			}
		} catch (IOException e) {
			throw new RoseRuntimeException(e);
		}
		return result.toString();
	}

	/**
	 * 字符串中下划线改成首字母大写格式
	 * 
	 * @param string 待格式化的字符串
	 * @return 格式化的字符串
	 */
	public static String underlineToLetterUpper(String string) {
		char[] charArray = string.toCharArray();
		// A-Z 对应数字65-90 a-z 对应数字97-122
		for (int i = 0; i < charArray.length; i++) {
			if (charArray[i] == '_') {
				// 字符在97-122之间的都是小写字母，在原基础上加32转换成大写
				if (charArray[i + 1] >= 97 && charArray[i + 1] <= 122) {
					int upper = charArray[i + 1] - 32;
					charArray[i + 1] = (char) upper;
				}
			}
		}
		// 首字母大写
		if (charArray[0] >= 97 && charArray[0] <= 122) {
			int upper = charArray[0] - 32;
			charArray[0] = (char) upper;
		}
		StringBuffer url = new StringBuffer("");
		for (int i = 0; i < charArray.length; i++) {
			url.append(charArray[i]);
		}
		return url.toString().replace("_", "");
	}

	private static final char[] hexDigit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
			'F' };

	/**
	 * 将整型转换成16进制
	 * 
	 * @param nibble 要转化的整型数值
	 * @return 转化后的16进制值
	 */
	private static char toHex(int nibble) {
		return hexDigit[(nibble & 0xF)];
	}

	/**
	 * 字节数组转16进制字符串
	 * 
	 * @param bytes 需要转换的byte数组
	 * @return 转换后的Hex字符串
	 */
	public static String bytesToHex(byte[] bytes) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < bytes.length; i++) {
			String hex = Integer.toHexString(bytes[i] & 0xFF);
			if (hex.length() < 2) {
				sb.append(0);
			}
			sb.append(hex);
		}
		return sb.toString();
	}

	/**
	 * 16进制hex字符串转byte数组
	 * 
	 * @param inHex 待转换的Hex字符串
	 * @return 转换后的byte数组结果
	 */
	public static byte[] hexToByteArray(String inHex) {
		int hexlen = inHex.length();
		byte[] result;
		if (hexlen % 2 == 1) {
			// 奇数
			hexlen++;
			result = new byte[(hexlen / 2)];
			inHex = "0" + inHex;
		} else {
			// 偶数
			result = new byte[(hexlen / 2)];
		}
		int j = 0;
		for (int i = 0; i < hexlen; i += 2) {
			result[j] = hexToByte(inHex.substring(i, i + 2));
			j++;
		}
		return result;
	}

	/**
	 * 16进制Hex字符串转byte
	 * 
	 * @param inHex 待转换的Hex字符串
	 * @return 转换后的byte
	 */
	public static byte hexToByte(String inHex) {
		return (byte) Integer.parseInt(inHex, 16);
	}

	/**
	 * 功能：Crc校验
	 * 
	 * @param data 需要校验的字符串参数
	 * @return 校验后的字符串
	 */
	public static String CRC16(String data) {
		byte[] temp = data.getBytes();
		int por = 0xffff;
		for (int j = 0; j < temp.length; j++) {
			por >>= 8;
			por ^= temp[j];
			for (int i = 0; i < 8; i++) {
				if ((por & 0x01) == 1) {
					por = por >> 1;
					por = por ^ 0xa001;
				} else
					por = por >> 1;
			}
		}
		return String.format("%04X", por);
	}

	/**
	 * ueditor用来转化unicode字符串
	 * 
	 * @param input 要转化的字符串
	 * @return 转化后的字符串
	 */
	public static String toUnicode(String input) {
		StringBuilder builder = new StringBuilder();
		char[] chars = input.toCharArray();
		for (char ch : chars) {
			if (ch < 256) {
				builder.append(ch);
			} else {
				builder.append("\\u" + Integer.toHexString(ch & 0xffff));
			}
		}
		return builder.toString();
	}

	/**
	 * 将字符串编码成 Unicode 。
	 * 
	 * @param theString   待转换成Unicode编码的字符串。
	 * @param escapeSpace 是否忽略空格。
	 * @return 返回转换后Unicode编码的字符串。
	 */
	public static String toUnicode(String theString, boolean escapeSpace) {
		int len = theString.length();
		int bufLen = len * 2;
		if (bufLen < 0) {
			bufLen = Integer.MAX_VALUE;
		}
		StringBuilder outBuffer = new StringBuilder(bufLen);

		for (int x = 0; x < len; x++) {
			char aChar = theString.charAt(x);
			// Handle common case first, selecting largest block that
			// avoids the specials below
			if ((aChar > 61) && (aChar < 127)) {
				if (aChar == '\\') {
					outBuffer.append('\\');
					outBuffer.append('\\');
					continue;
				}
				outBuffer.append(aChar);
				continue;
			}
			switch (aChar) {
				case ' ':
					if (x == 0 || escapeSpace)
						outBuffer.append('\\');
					outBuffer.append(' ');
					break;
				case '\t':
					outBuffer.append('\\');
					outBuffer.append('t');
					break;
				case '\n':
					outBuffer.append('\\');
					outBuffer.append('n');
					break;
				case '\r':
					outBuffer.append('\\');
					outBuffer.append('r');
					break;
				case '\f':
					outBuffer.append('\\');
					outBuffer.append('f');
					break;
				case '=': // Fall through
				case ':': // Fall through
				case '#': // Fall through
				case '!':
					outBuffer.append('\\');
					outBuffer.append(aChar);
					break;
				default:
					if ((aChar < 0x0020) || (aChar > 0x007e)) {
						outBuffer.append('\\');
						outBuffer.append('u');
						outBuffer.append(toHex((aChar >> 12) & 0xF));
						outBuffer.append(toHex((aChar >> 8) & 0xF));
						outBuffer.append(toHex((aChar >> 4) & 0xF));
						outBuffer.append(toHex(aChar & 0xF));
					} else {
						outBuffer.append(aChar);
					}
			}
		}
		return outBuffer.toString();
	}

	/**
	 * 从 Unicode码转换成编码前的特殊字符串。
	 * 
	 * @param in  Unicode编码的字符数组。
	 * @param off 转换的起始偏移量。
	 * @param len 转换的字符长度。
	 * @return 完成转换，返回编码前的特殊字符串。
	 */
	public static String fromUnicode(char[] in, int off, int len) {
		int newLen = len * 2;
		if (newLen < 0) {
			newLen = Integer.MAX_VALUE;
		}

		char aChar;
		char[] out = new char[newLen];
		int outLen = 0;
		int end = off + len;

		while (off < end) {
			aChar = in[off++];
			if (aChar == '\\') {
				aChar = in[off++];
				if (aChar == 'u') {
					// Read the xxxx
					int value = 0;
					for (int i = 0; i < 4; i++) {
						aChar = in[off++];
						switch (aChar) {
							case '0':
							case '1':
							case '2':
							case '3':
							case '4':
							case '5':
							case '6':
							case '7':
							case '8':
							case '9':
								value = (value << 4) + aChar - '0';
								break;
							case 'a':
							case 'b':
							case 'c':
							case 'd':
							case 'e':
							case 'f':
								value = (value << 4) + 10 + aChar - 'a';
								break;
							case 'A':
							case 'B':
							case 'C':
							case 'D':
							case 'E':
							case 'F':
								value = (value << 4) + 10 + aChar - 'A';
								break;
							default:
								throw new IllegalArgumentException("Malformed \\uxxxx encoding.");
						}
					}
					out[outLen++] = (char) value;
				} else {
					if (aChar == 't') {
						aChar = '\t';
					} else if (aChar == 'r') {
						aChar = '\r';
					} else if (aChar == 'n') {
						aChar = '\n';
					} else if (aChar == 'f') {
						aChar = '\f';
					}
					out[outLen++] = aChar;
				}
			} else {
				out[outLen++] = aChar;
			}
		}
		return new String(out, 0, outLen);
	}

	/**
	 * 功能：格式化字符串 例：str = "你好{0},我是{1}";args = {"张三","李四"} 结果：你好张天，我是李辊
	 * 
	 * @param str  待格式化的字符串
	 * @param args 参数
	 * @return 格式化后的字段串
	 */
	public static String format(String str, String... args) {
		for (int i = 0; i < args.length; i++) {
			String key = "{" + i + '}';
			str = StringUtils.replace(str, key, args[i]);
		}
		return str;
	}

	/**
	 * 功能：格式化字符串 例：str = "你好{name},我是{name2}";map = {name:"张三",name2:"李四"}
	 * 结果：你好张天，我是李辊
	 * 
	 * @param str 待格式化的字符串
	 * @param map 参数
	 * @return 格式化后的字段串
	 */
	public static String format(String str, Map<String, String> map) {
		for (String s : map.keySet()) {
			String key = "{" + s + '}';
			str = StringUtils.replace(str, key, map.get(s));
		}
		return str;
	}

	/**
	 * 功能：格式化字符串 例：str = "你好#name#,我是#name2#";map = {name:"张三",name2:"李四"}
	 * 结果：你好张天，我是李辊
	 * 
	 * @param str 待格式化的字符串
	 * @param map 参数
	 * @return 格式化后的字段串
	 */
	public static String format2(String str, Map<String, String> map) {
		for (String s : map.keySet()) {
			String key = "#" + s + '#';
			str = StringUtils.replace(str, key, map.get(s));
		}
		return str;
	}

	private static SerializeConfig mapping = new SerializeConfig();

	static {
		String dateFormat = "yyyy-MM-dd HH:mm:ss";
		mapping.put(Date.class, new SimpleDateFormatSerializer(dateFormat));
		mapping.put(Timestamp.class, new SimpleDateFormatSerializer(dateFormat));
	}

	/**
	 * 将对象类型数据转化为json字符串.
	 * 
	 * @param object 待转的对象数据类
	 * @return 转换后的结果字符串
	 */
	public static String render(Object object) {
		return JSON.toJSONString(object, mapping);
	}

	/**
	 * 将实体对象转化为json字符串.
	 * 
	 * @param object  待转的对象数据类
	 * @param mapping 转换器适配器定义
	 * @return 转换后的结果字符串
	 */
	public static String render(Object object, SerializeConfig mapping) {
		return JSON.toJSONString(object, mapping);
	}

	/**
	 * 将字符串转换成实体对象
	 * 
	 * @param <T>        返回的数据类型
	 * @param clazz      转换的目标对象实体类
	 * @param jsonString 待转化的json字符串
	 * @return 转换后的结果对象实体类
	 */
	public static <T> T parseJson(Class<T> clazz, String jsonString) {
		return JSON.parseObject(jsonString, clazz);
	}

	/**
	 * 将json字符串转化为对象类型数据.
	 * 
	 * @param <T>        返回的数据类型
	 * @param clazz      转换的目标对象实体类
	 * @param jsonString 待转化的json字符串
	 * @return 转换后的结果实体类列表
	 */
	public static <T> List<T> parseJsonArray(Class<T> clazz, String jsonString) {
		List<T> list = new ArrayList<>();
		JSONArray array = JSON.parseArray(jsonString);
		for (Object obj : array) {
			list.add(parseJson(clazz, obj.toString()));
		}
		return list;
	}

	/**
	 * 将Json格式的字符串直接转成Map类型
	 * 
	 * @param jsonString 待转的对象字符串
	 * @return 结果Map对象
	 */
	public static Map<String, Object> parseJson(String jsonString) {
		JSONObject json = JSON.parseObject(jsonString);
		return parseJson(json);
	}

	/**
	 * 将Json格式的字符串直接转成Map类型
	 * 
	 * @param jsonString 待转的对象字符串
	 * @return 结果Map对象
	 */
	public static Map<String, Object> parseJson(JSONObject json) {
		Object val = null;
		Map<String, Object> map = new HashMap<>();
		for (String key : json.keySet()) {
			val = json.get(key);
			if (val != null) {
				if (val instanceof JSONObject) {
					map.put(key, parseJson((JSONObject) val));
				} else if (val instanceof JSONArray) {
					map.put(key, parseJsonArray((JSONArray) val));
				} else {
					map.put(key, val);
				}
			}
		}
		return map;
	}

	/**
	 * 将Json格式的字符串直接转成Map类型
	 * 
	 * @param jsonString 待转的对象字符串
	 * @return 结果Map对象
	 */
	public static List<Object> parseJsonArray(String jsonString) {
		JSONArray array = JSON.parseArray(jsonString);
		return parseJsonArray(array);
	}

	/**
	 * 将Json格式的字符串直接转成Map类型
	 * 
	 * @param jsonString 待转的对象字符串
	 * @return 结果Map对象
	 */
	public static List<Object> parseJsonArray(JSONArray array) {
		List<Object> list = new ArrayList<>();
		for (Object obj : array) {
			if (obj != null) {
				if (obj instanceof JSONObject) {
					list.add(parseJson((JSONObject) obj));
				} else if (obj instanceof JSONArray) {
					list.add(parseJsonArray((JSONArray) obj));
				} else {
					list.add(obj);
				}
			}
		}
		return list;
	}

	/**
	 * 将Web请求参数格式的字符串直接转成Map类型
	 * 
	 * @param string 待转的对象字符串
	 * @return 结果Map对象
	 */
	public static Map<String, Object> parseString(String string) {
		Map<String, Object> map = new HashMap<>();
		if (string == null || string.length() == 0) {
			return map;
		}
		try {
			if (string.indexOf('&') != -1) {
				for (String kv : string.split("&")) {
					String[] temp = kv.split("=");
					if (temp.length == 2) {
						map.put(temp[0], URLDecoder.decode(temp[1], "utf-8"));
					}
				}
			} else if (string.indexOf('=') != -1) {
				String[] temp = string.split("=");
				if (temp.length == 2) {
					map.put(temp[0], URLDecoder.decode(temp[1], "utf-8"));
				}
			}
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e.getMessage(), e);
		}
		return map;
	}

	private static byte[] aesKey = null;

	private static AesEncrypt aes = new AesEncrypt();

	/**
	 * 设置加密密钥
	 * 
	 * @param aesKey 加密密钥
	 */
	public static void setAesKey(String aesKey) {
		try {
			StringUtil.aesKey = aesKey.getBytes("UTF-8");
		} catch (Exception e) {
			throw new RuntimeException("加密密钥设置失败！\n" + e.getMessage(), e);
		}
	}

	/**
	 * 将字符串加密
	 * 
	 * @param str 待加密的字符串
	 * @return 加密后的字符串
	 */
	public static String encrypt(String str) {
		// 如果初始化失败
		if (!InitialCrypt()) {
			return null;
		}
		try {
			byte[] bytes = aes.encrypt(str.getBytes("UTF-8"), aesKey, false, aesKey);
			return Base64.encodeBase64String(bytes);
		} catch (Exception e) {
			throw new RuntimeException("字符串" + str + "加密失败！\n" + e.getMessage(), e);
		}
	}

	/**
	 * 将字符串解密
	 * 
	 * @param str 等解密的字符串
	 * @return 解密后的字符串
	 */
	public static String decrypt(String str) {
		// 如果初始化失败
		if (!InitialCrypt()) {
			return null;
		}
		try {
			byte[] bytes = Base64.decodeBase64(str);
			bytes = aes.decrypt(bytes, aesKey, false, aesKey);
			return new String(bytes, "UTF-8");
		} catch (Exception e) {
			throw new RuntimeException("字符串" + str + "解密失败！\n" + e.getMessage(), e);
		}
	}

	private static boolean InitialCrypt() {
		if (aesKey == null) {
			try {
				// 生成加密密钥
				aesKey = "3206011981012647".getBytes("UTF-8");
				return true;
			} catch (Exception e) {
				e.printStackTrace();
				return false;
			}
		}
		return true;
	}

	/** 汉语中数字大写 */
	private static final String[] CN_UPPER_NUMBER = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };

	/** 汉语中货币单位大写，这样的设计类似于占位符 */
	private static final String[] CN_UPPER_MONETRAY_UNIT = { "分", "角", "元", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾",
			"佰", "仟", "兆", "拾", "佰", "仟" };

	/** * 特殊字符：整 */
	private static final String CN_FULL = "整";

	/** 特殊字符：负 */
	private static final String CN_NEGATIVE = "负";

	/** 金额的精度，默认值为2 */
	private static final int MONEY_PRECISION = 2;

	/** 特殊字符：零元整 */
	private static final String CN_ZEOR_FULL = "零元" + CN_FULL;

	/**
	 * 把输入的金额转换为汉语中人民币的大写
	 * 
	 * @param numberOfMoney 输入的金额
	 * @return 对应的汉语大写
	 */
	public static String toCnMoney(double numberOfMoney) {
		return toCnMoney(new BigDecimal(numberOfMoney));
	}

	/**
	 * 把输入的金额转换为汉语中人民币的大写
	 * 
	 * @param numberOfMoney 输入的金额
	 * @return 对应的汉语大写
	 */
	public static String toCnMoney(BigDecimal numberOfMoney) {
		StringBuffer sb = new StringBuffer();
		// -1, 0, or 1 as the value of this BigDecimal is negative, zero, or
		// positive.
		int signum = numberOfMoney.signum();
		// 零元整的情况
		if (signum == 0) {
			return CN_ZEOR_FULL;
		}
		// 这里会进行金额的四舍五入
		long number = numberOfMoney.movePointRight(MONEY_PRECISION).setScale(0, 4).abs().longValue();
		// 得到小数点后两位值
		long scale = number % 100;
		int numUnit = 0;
		int numIndex = 0;
		boolean getZero = false;
		// 判断最后两位数，一共有四中情况：00 = 0, 01 = 1, 10, 11
		if (!(scale > 0)) {
			numIndex = 2;
			number = number / 100;
			getZero = true;
		}
		if ((scale > 0) && (!(scale % 10 > 0))) {
			numIndex = 1;
			number = number / 10;
			getZero = true;
		}
		int zeroSize = 0;
		while (true) {
			if (number <= 0) {
				break;
			}
			// 每次获取到最后一个数
			numUnit = (int) (number % 10);
			if (numUnit > 0) {
				if ((numIndex == 9) && (zeroSize >= 3)) {
					sb.insert(0, CN_UPPER_MONETRAY_UNIT[6]);
				}
				if ((numIndex == 13) && (zeroSize >= 3)) {
					sb.insert(0, CN_UPPER_MONETRAY_UNIT[10]);
				}
				sb.insert(0, CN_UPPER_MONETRAY_UNIT[numIndex]);
				sb.insert(0, CN_UPPER_NUMBER[numUnit]);
				getZero = false;
				zeroSize = 0;
			} else {
				++zeroSize;
				if (!(getZero)) {
					sb.insert(0, CN_UPPER_NUMBER[numUnit]);
				}
				if (numIndex == 2) {
					if (number > 0) {
						sb.insert(0, CN_UPPER_MONETRAY_UNIT[numIndex]);
					}
				} else if (((numIndex - 2) % 4 == 0) && (number % 1000 > 0)) {
					sb.insert(0, CN_UPPER_MONETRAY_UNIT[numIndex]);
				}
				getZero = true;
			}
			// 让number每次都去掉最后一个数
			number = number / 10;
			++numIndex;
		}
		// 如果signum == -1，则说明输入的数字为负数，就在最前面追加特殊字符：负
		if (signum == -1) {
			sb.insert(0, CN_NEGATIVE);
		}
		// 输入的数字小数点后两位为"00"的情况，则要在最后追加特殊字符：整
		if (!(scale > 0)) {
			sb.append(CN_FULL);
		}
		return sb.toString();
	}

	private static final char last2byte = (char) Integer.parseInt("00000011", 2);
	private static final char last4byte = (char) Integer.parseInt("00001111", 2);
	private static final char last6byte = (char) Integer.parseInt("00111111", 2);
	private static final char lead6byte = (char) Integer.parseInt("11111100", 2);
	private static final char lead4byte = (char) Integer.parseInt("11110000", 2);
	private static final char lead2byte = (char) Integer.parseInt("11000000", 2);
	private static final char[] encodeTable = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
			'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
			'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1',
			'2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };

	/**
	 * 百度API将二进制转换成字符串
	 * 
	 * @param from 二进制数组
	 * @return 转换后的字符串
	 */
	public static String toBase64(byte[] from) {
		StringBuilder to = new StringBuilder((int) ((double) from.length * 1.34D) + 3);
		int num = 0;
		char currentByte = 0;
		int i;
		for (i = 0; i < from.length; ++i) {
			for (num %= 8; num < 8; num += 6) {
				switch (num) {
					case 0:
						currentByte = (char) (from[i] & lead6byte);
						currentByte = (char) (currentByte >>> 2);
					case 1:
					case 3:
					case 5:
					default:
						break;
					case 2:
						currentByte = (char) (from[i] & last6byte);
						break;
					case 4:
						currentByte = (char) (from[i] & last4byte);
						currentByte = (char) (currentByte << 2);
						if (i + 1 < from.length) {
							currentByte = (char) (currentByte | (from[i + 1] & lead2byte) >>> 6);
						}
						break;
					case 6:
						currentByte = (char) (from[i] & last2byte);
						currentByte = (char) (currentByte << 4);
						if (i + 1 < from.length) {
							currentByte = (char) (currentByte | (from[i + 1] & lead4byte) >>> 4);
						}
				}
				to.append(encodeTable[currentByte]);
			}
		}
		if (to.length() % 4 != 0) {
			for (i = 4 - to.length() % 4; i > 0; --i) {
				to.append("=");
			}
		}
		return to.toString();
	}

	public static String getLanguagePrefix(String language) {
		String languagePrefix = null;
		if (language.equals("zh")) {
			languagePrefix = "C";
		} else if (language.equals("en")) {
			languagePrefix = "E";
		} else if (language.equals("jp")) {
			languagePrefix = "J";
		}
		return languagePrefix;
	}

	/**
	 * 判断字符串中是否包含中文
	 * <p>
	 * 注意不能校验是否为中文标点符号
	 * 
	 * @param str 待校验字符串
	 * @return 是否为中文
	 */
	public static boolean isContainChinese(String str) {
		Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
		Matcher m = p.matcher(str);
		if (m.find()) {
			return true;
		}
		return false;
	}

	// 获得MD5摘要算法的 MessageDigest 对象
	private static MessageDigest _mdInst = null;
	// 自定义的字符串组合(为安全考虑，建议使用自定义的密码字符串组合)
	public static char hexDigits[] = { '8', '9', '7', '4', '5', '0', '2', '6', '3', '1', 'C', 'D', 'A', 'B', 'E',
			'F' };
	// 默认的密码字符串组合，用来将字节转换成 16
	// 进制表示的字符,apache校验下载的文件的正确性用的就是默认的这个组合（使用这个的话用在线解密工具可能会破解）
	private static char hexDigits2[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e',
			'f' };

	private static MessageDigest getMdInst() {
		if (_mdInst == null) {
			try {
				_mdInst = MessageDigest.getInstance("MD5");
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
			}
		}
		return _mdInst;
	}

	/***
	 * MD5加密 生成32位md5码
	 * 
	 * @param inStr 待加密字符串
	 * @return 返回32位md5码
	 */
	public static String md5Encode(String inStr) {
		try {
			byte[] btInput = inStr.getBytes("utf-8");
			// 使用指定的字节更新摘要
			getMdInst().update(btInput);
			// 获得密文
			byte[] md = getMdInst().digest();
			// 把密文转换成十六进制的字符串形式
			int j = md.length;
			char str[] = new char[j * 2];
			int k = 0;
			for (byte byte0 : md) {
				str[k++] = hexDigits2[byte0 >>> 4 & 0xf];
				str[k++] = hexDigits2[byte0 & 0xf];
			}
			return new String(str);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public static void main(String[] args) {
		double money = 2020004.01;
		BigDecimal numberOfMoney = new BigDecimal(money);
		String s = toCnMoney(numberOfMoney);
		System.out.println("你输入的金额为：【" + money + "】   #--# [" + s.toString() + "]");
		System.out.println(underlineToLetterUpper("aa_bb_cc"));
	}

}
